package com.alameda.listener.strategy.impl;

import com.alameda.api.user.UserOperateLogService;
import com.alameda.base.constant.ProjectConstant;
import com.alameda.listener.strategy.api.ListenerStrategy;
import com.alameda.user.dto.UserDTO;
import com.alameda.user.dto.UserOperateLogDTO;
import com.alameda.utils.ObjectUtils;
import com.alameda.utils.PubUtils;
import com.alameda.utils.ThreadLocalUtils;
import com.alameda.utils.ThreadPoolUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Optional;

/**
 * 监听策略 日志监听
 *
 * @author Lv
 * @date 2025/3/3
 */
@Component(ProjectConstant.StrategyConstant.OPERATE_STRATEGY)
public class OperateLogStrategyImpl implements ListenerStrategy {

    @Autowired
    private UserOperateLogService userOperateLogService;

    /**
     * 监听消息
     *
     * @param map 消息内容
     */
    @Override
    public void listenEvent(Map<String, Object> map) {
        // 获取账号
        String userName = PubUtils.isNull(ThreadLocalUtils.getParseResult()) || PubUtils.isEmpty(ThreadLocalUtils.getUserName())
                ? getUserName(map)
                : ThreadLocalUtils.getUserName();

        UserOperateLogDTO userOperateLogDTO = new UserOperateLogDTO();
        userOperateLogDTO.setUserName(userName);
        userOperateLogDTO.setOperateApiName((String) map.get(ProjectConstant.OperateInfoPropertyConstant.API_NAME));
        userOperateLogDTO.setOperateApiTime(LocalDateTime.now());
        userOperateLogDTO.setOperateApiResult((String) map.get(ProjectConstant.OperateInfoPropertyConstant.OPERATE_RESULT));
        userOperateLogDTO.setOperateApiTraceId((String) map.get(ProjectConstant.OperateInfoPropertyConstant.TRACE_ID));

        // 异步保存日志
        ThreadPoolUtils.execute(() -> userOperateLogService.saveOperateLogInfo(userOperateLogDTO));
    }

    /**
     * 获取用户账号
     *
     * @param map 事件消息内容
     * @return
     */
    private String getUserName(Map<String, Object> map) {
        Object requestParam = map.get(ProjectConstant.OperateInfoPropertyConstant.REQUEST_PARAM);
        UserDTO apUserDTO = ObjectUtils.convert(requestParam, UserDTO.class);
        return Optional.ofNullable(apUserDTO).orElse(UserDTO.builder().build()).getUsername();
    }
}
